//
//  APIs.m
//  FishTank
//
//  Created by Scott Zhu on 14/11/26.
//  Copyright (c) 2014年 Scott Zhu. All rights reserved.
//

#import "APIs.h"
#import <dispatch/dispatch.h>
#import "DeviceSun.h"
#import "iPN_API.h"

@interface APIs ()
@property (nonatomic) dispatch_queue_t controlQueue;
@property (nonatomic) dispatch_queue_t videoQueue;
@property (nonatomic) dispatch_queue_t closeQueue;
@property (nonatomic) NSString * lastConnectTarget;//最近一次连接的设备ID
@end

@implementation APIs
@synthesize controlQueue = _controlQueue;
@synthesize videoQueue = _videoQueue;
@synthesize isListenOnSensors = _isListenOnSensors;
@synthesize isListenOnVideo = _isListenOnVideo;
@synthesize isQuerySubscribeToken = _isQuerySubscribeToken;

+ (APIs *)sharedInstance
{
    static APIs *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[APIs alloc] init];
    });
    return sharedInstance;
}

- (instancetype)init
{
    self = [super init];
    if (self)
    {
        _errorOfSensorCnt = 0;
        _errorOfVideoCnt = 0;
        
        INT32 ret = PPPP_Initialize((CHAR *)"AACCEIAHKBNIHJNGEDHJAGEGGOJIDINAGMFKFECGEPJIKIPBDNBFHPLJGDLAIAPBAEJBKCCGKHNHAP");
        
        if(ret == ERROR_PPPP_SUCCESSFUL){
            NSLog(@"PPPP Init 成功: %ld", (long)ret);
        }else{
            NSLog(@"PPPP Init 失败: %ld", (long)ret);
        }
        
        self.currentSession = -1;
        _isListenOnSensors = NO;
    }
    return self;
}

- (NSString *)version
{
    UINT32 apiVersion = PPPP_GetAPIVersion();
    NSLog(@"API Version = %d", apiVersion);
    return [NSString stringWithFormat:@"%d", apiVersion];
}


/**
 * 检查PPPP
 */
-(BOOL) checkPPPP{
    
    if(self.currentSession != -1){
        
        st_PPPP_Session   sessionInfo ;
        
        INT32 check_ret = PPPP_Check(self.currentSession, &sessionInfo);
        
        //    if(check_ret){
        switch (check_ret) {
            case ERROR_PPPP_SUCCESSFUL:
                NSLog(@"DID=%s,ConnectTime= %u",sessionInfo.DID,sessionInfo.ConnectTime);
                NSLog(@"设备还是客户端=%hhd,bMode= %u",sessionInfo.bCorD,sessionInfo.bMode);
                break;
            case ERROR_PPPP_NOT_INITIALIZED:
            {
                return NO;
            }
                break;
            case ERROR_PPPP_INVALID_PARAMETER:
                NSLog(@"PPPP_Check 无效参数");
                break;
            case ERROR_PPPP_INVALID_SESSION_HANDLE:
                NSLog(@"PPPP_Check 无效Session句柄");
            case ERROR_PPPP_SESSION_CLOSED_CALLED:
                NSLog(@"PPPP_Check 会话关闭");
            case ERROR_PPPP_SESSION_CLOSED_TIMEOUT:
                NSLog(@"PPPP_Check 会话超时");
            case ERROR_PPPP_SESSION_CLOSED_REMOTE:
                NSLog(@"PPPP_Check 远程会话关闭");
                return NO;
                break;
            default:
                NSLog(@"PPPP_Check 未知返回");
                break;
        }
    }
    //END
    return YES;
}

-(void)reconnect:(void (^)(NSInteger))success
         failure:(void (^)(NSInteger))failure{
    //    [self close];
    [self connectWithUid:self.lastConnectTarget lanSearchEnable:YES
                 success:^(NSInteger  session){
                     success(session);
                 } failure:^(NSInteger  errcode){
                     failure(errcode);
                 }];
}






/*寻找设备并连接上设备
 *
 * @param targetID 设备ID
 */
- (NSInteger)connectWithUid:(NSString *)targetID
            lanSearchEnable:(BOOL)enable
                    success:(void (^)(NSInteger))success
                    failure:(void (^)(NSInteger))failure
{
    
    NSLog(@"targetID = %s",[targetID UTF8String]);
    self.lastConnectTarget = targetID;
    INT32 ret  = PPPP_Connect(targetID.UTF8String, enable, 0);
    
    if( 0 <= ret )
    {
        self.currentSession = ret;
        success(ret);
    }
    else
    {
        failure(ret);
    }
    
    return ret;
}


//设备锁定状态获取
- (void)getDeviceLockStatusWithPassword:(NSString *)password
                                success:(void (^)(NSString * lockStatus))success
                             interupted:(void (^)(NSInteger errorCode))interupted{
    
    _isListenOnSensors = YES;
    dispatch_async(self.controlQueue, ^
                   {
                       NSLog(@"Start listen on sensors.......");
                       while (_isListenOnSensors)
                       {
                           NSInteger ret = -99;
                           
                           NSLog(@"sendSensorReadingRequest ret = %ld", (long)[self sendSensorReadingRequest:password]);
                           //            [NSThread sleepForTimeInterval:1];
                           
                           ClientPackHead headBuf;
                           int headSize = sizeof(headBuf);
                           ret = PPPP_Read(self.currentSession, (UCHAR)1, (CHAR *)&headBuf, &headSize, 0xffffffff);
                           NSLog(@"PPPP_Read ret1 = %ld", (long)ret);
                           
                           if (ERROR_PPPP_SUCCESSFUL <= ret && 0xaa == headBuf.flag && CPT_MCU_COMM_FB == headBuf.type)
                           {
                               int bodySize = headBuf.length;
                               char *bodyBuf = (char *)malloc(sizeof(char) * bodySize);
                               NSInteger bodyRet = PPPP_Read(self.currentSession, (UCHAR)1, bodyBuf, &bodySize, 0xffffffff);
                               if (bodyRet >= 0)
                               {
                                   float lock = (short)bodyBuf[34];
                                   NSString * status = [NSString stringWithFormat:@"%f", lock];
                                   dispatch_async(dispatch_get_main_queue(), ^{
                                       success(status);
                                   });
                               }
                           }
//                           [NSThread sleepForTimeInterval:1];
                       }
                       dispatch_async(dispatch_get_main_queue(), ^{
                           interupted(0);
                       });
                   });

    
}



//设备锁定与解锁
- (void)deviceLockOrUnlockWithpassword:(NSString *)password
                           LockOStatus:(BOOL)lockStatus
                               success:(void (^)(BOOL status))success
                            interupted:(void (^)(NSInteger errorCode))interupted
{
    
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        NSInteger ret = -99;
        /** Build the request data block*/
        UInt8 data[2];
        data[0] = 0x13;
        
        if (lockStatus) {
             data[1] = 0x01;//锁定设备
        }else{
             data[1] = 0x00;//解除设备锁定
        }
        
        ControlRequest request;
        request.head.flag = 0xaa;
        request.head.type = CPT_MCU_COMM;
        request.head.length = (int)(sizeof(data) / sizeof(data[0])) + 18;//18 == sizeof(pwd)+sizeof(mode) + sizeof(length)
        memcpy(request.body.devPwd, [password UTF8String], sizeof(request.body.devPwd));
        request.body.mode = SET;
        request.body.length = (int)(sizeof(data) / sizeof(data[0]));
        memcpy(request.body.content, data, sizeof(data));
        
        NSData *requestBodyInByte = [NSData dataWithBytes:&request length:sizeof(request)];
        NSLog(@"requestBodyInByte = %@ ; size of request = %lu", requestBodyInByte, sizeof(request));

        
          PPPP_Write(self.currentSession, (UCHAR)1, (CHAR *)[requestBodyInByte bytes], sizeof(request));
        
        //[NSThread sleepForTimeInterval:1];
        
        ClientPackHead headBuf;
        int headSize = sizeof(headBuf);
        ret = PPPP_Read(self.currentSession, (UCHAR)1, (CHAR *)&headBuf, &headSize, 0xffffffff);
        if (ERROR_PPPP_SUCCESSFUL == ret && 0xaa == headBuf.flag && CPT_MCU_COMM_FB == headBuf.type)
        {
            int bodySize = headBuf.length;
            char *bodyBuf = (char *)malloc(sizeof(char) * bodySize);
            NSInteger bodyRet = PPPP_Read(self.currentSession, (UCHAR)1, bodyBuf, &bodySize, 0xffffffff);
            if (bodyRet >= 0)
            {
                
                float lock = (short)bodyBuf[34];
                NSString * status = [NSString stringWithFormat:@"%f", lock];
                dispatch_async(dispatch_get_main_queue(), ^{
                    success(status);
                });

            
            }
        }
        
        dispatch_async(dispatch_get_main_queue(), ^{
            interupted(0);
        });


    });

    
}



//设备版本获取
- (void)getDeviceVersionWithpassword:(NSString *)password
                             timeout:(UINT32) timeout
                             success:(void (^)(DeviceMainVersion  version,NSString * mainVersion, NSString * majorVersion))success
                          interupted:(void (^)(NSInteger errorCode))interupted
{

//    UINT32 timeout = 10000;//10秒
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        INT32 ret = -99;
        /** Build the request data block*/
        UInt8 data[2];
        data[0] = 0x20;
        data[1] = 0x20;
        
        ControlRequest request;
        request.head.flag = 0xaa;
        request.head.type = CPT_MCU_COMM;
        request.head.length = (int)(sizeof(data) / sizeof(data[0])) + 18;//18 == sizeof(pwd)+sizeof(mode) + sizeof(length)
        memcpy(request.body.devPwd, [password UTF8String], sizeof(request.body.devPwd));
        request.body.mode = READ;
        request.body.length = (int)(sizeof(data) / sizeof(data[0]));
        memcpy(request.body.content, data, sizeof(data));
        
        NSData *requestBodyInByte = [NSData dataWithBytes:&request length:sizeof(request)];
        
       ret = PPPP_Write(self.currentSession, (UCHAR)1, (CHAR *)[requestBodyInByte bytes], sizeof(request));
        if(ret < 0){
            NSLog(@"设备版本获取请求= %@",[DeviceCtrl getPPPPWriteMsg:ret]);
            dispatch_async(dispatch_get_main_queue(), ^{
                interupted(0);
            });
            return ;
        }
        
        
        BOOL isSuccess = NO;
        ClientPackHead headBuf;
        int headSize = sizeof(headBuf);
        ret = PPPP_Read(self.currentSession, (UCHAR)1, (CHAR *)&headBuf, &headSize, timeout);
        
        NSLog(@"设备获取版本信息 PPPP_Read ＝ %d desc= %@", ret,[DeviceCtrl getPPPPReadMsg:ret]);
        
        if (ERROR_PPPP_SUCCESSFUL == ret && 0xaa == headBuf.flag && CPT_MCU_COMM_FB == headBuf.type)
        {
            int bodySize = headBuf.length;
            char *bodyBuf = (char *)malloc(sizeof(char) * bodySize);
            INT32 bodyRet = PPPP_Read(self.currentSession, (UCHAR)1, bodyBuf, &bodySize, timeout);
            
            NSLog(@"bodyRet ＝ %d desc= %@", bodyRet,[DeviceCtrl getPPPPReadMsg:bodyRet]);//23   0001 0111

            if (bodyRet == ERROR_PPPP_SUCCESSFUL)
            {
                
                char mainVersion = bodyBuf[1];//主版本
                char minVersion = bodyBuf[2];//次版本号
                //0x17：设备挂载AQ107底板
//                0x29：设备挂载AQ209底板
//                0x85：设备挂载AQ805底板
//                0x21: 设备挂载AQ211底板
                NSString * strMainVersion =  [NSString stringWithFormat:@"%d",mainVersion];
                NSString * strMinVersion = [NSString stringWithFormat:@"%d",minVersion];
                DeviceMainVersion version = AQ000;
                
                if((mainVersion & AQ805) == AQ805){
                    strMainVersion = @"AQ805";
                    version = AQ805;
                }else if((mainVersion & AQ107) == AQ107){
                    strMainVersion = @"AQ107";
                    version = AQ107;
                }else if((mainVersion & AQ209) == AQ209){
                    strMainVersion = @"AQ209";
                    version = AQ209;
                }else if ((mainVersion & AQ211) == AQ211){
                    strMainVersion = @"AQ211";
                    version = AQ211;
                }
                
                NSLog(@"主版本=%@,次版本=%@",strMainVersion,strMinVersion);
                isSuccess = YES;
                dispatch_async(dispatch_get_main_queue(), ^{
                    success(version,strMainVersion,strMinVersion);
                });
            }
        }
        
        if(!isSuccess){
            dispatch_async(dispatch_get_main_queue(), ^{
                interupted(0);
            });
        }
        
        
    });
    
}






- (void) listenOnSensorsWithTimeout: (NSUInteger)timeout
                           password: (NSString *)password
                            updated:(void (^)(float temperature, float ph, Byte controlByte, NSString *lockStatus))updated
                         interupted:(void (^)(NSInteger errorCode))interupted
{

    _isListenOnSensors = YES;
    dispatch_async(self.controlQueue, ^{
        
                NSLog(@"Start listen on sensors.......");
                while (_isListenOnSensors)
                {
                    if(self.errorOfSensorCnt > MAX_STATE_ERROR_CNT){
                        dispatch_async(dispatch_get_main_queue(), ^{
                            interupted(ERROR_NEED_RECONNECT);
                            self.errorOfSensorCnt = 0;
                        });
                        break;
                    }
                           
                    INT32 ret = -99;
                    ret = [self sendSensorReadingRequest:password];
                    
                    ClientPackHead headBuf;
                    int headSize = sizeof(headBuf);

                    ret = PPPP_Read(self.currentSession, (UCHAR)1, (CHAR *)&headBuf, &headSize, (UINT32)timeout);
                    
                    if (ERROR_PPPP_SUCCESSFUL == ret && 0xaa == headBuf.flag && CPT_MCU_COMM_FB == headBuf.type)
                    {
                        int bodySize = headBuf.length;
                        char *bodyBuf = (char *)malloc(sizeof(char) * bodySize);
                        INT32 bodyRet = PPPP_Read(self.currentSession, (UCHAR)1, bodyBuf, &bodySize, (UINT32)timeout);
                        
                        if (bodyRet == ERROR_PPPP_SUCCESSFUL)
                        {
                            //用于保存设备全局状态
                            DeviceSun * device = [DeviceSun defaultDevice];
                                   
                            [self getDateFromGlobalState:bodyBuf :bodySize];
                                   
                            float temperature = (short)((bodyBuf[1] << 8) | (bodyBuf[2] & 0xff)) / (float)10;
                            float ph = (short)((bodyBuf[3] << 8) | (bodyBuf[4] & 0xff)) / (float)100;
                            int lock = (int)bodyBuf[34];//锁定状态
                            int low = (int)((bodyBuf[37] << 8) | (bodyBuf[38] & 0xff)) / 10;//低温阙值
                            int high= (int)((bodyBuf[39] << 8) | (bodyBuf[40] & 0xff)) / 10;//高温阙值
                            
                            int highTemperature = (int)((bodyBuf[32] << 8) | (bodyBuf[33] & 0xff)) / 10;//高温阙值
                            
                            
                            
                            //单片机全局状态  故障状态
                            int failureState = (int)((bodyBuf[35] << 8) | (bodyBuf[36] & 0xff));//故障状态
                            int waterTemperature = failureState & 0x0003;//水温状态
                            int lamp = failureState & 0x0004;//杀菌灯状态
                            int waterPump = failureState & 0x0008;//冲浪水泵
                            int floodlight = failureState & 0x0010;//照明灯
                            int standbyPower = failureState & 0x0020;//备用电源
                            int waterLevel = failureState & 0x0040;//水位
                            int pH = failureState & 0x0300;//PH值
                            
                            
                    
                            //如果它存在44个长度  说明是挂载AQ211底板
                            if (bodySize >43) {
                    
                                int cyclePumpPower = (int)(bodyBuf[41]);//循环水泵功率
                                int lampPower = (int)(bodyBuf[42]);//杀菌灯功率
                                int waterPumpPower = (int)(bodyBuf[43]);//冲浪水泵功率
                                int floodlightPower = (int)(bodyBuf[44]);//灯光功率


                                if (cyclePumpPower > 99 || cyclePumpPower < 0) {
                                    cyclePumpPower = 0;
                                }
                                
                                if (lampPower > 99 || lampPower < 0) {
                                    lampPower = 0;
                                }

                                if (waterPumpPower > 99 || waterPumpPower < 0) {
                                    waterPumpPower = 0;
                                }

                                if (floodlightPower > 99 || floodlightPower < 0) {
                                    floodlightPower = 0;
                                }

                                device.cyclePumpPower = cyclePumpPower;
                                device.lampPower = lampPower;
                                device.waterPumpPower = waterPumpPower;
                                device.floodlightPower = floodlightPower;
                            }
                            
                            
                            if (low > 100 || low < 0) {
                                low = 0;
                            }

                            if (high > 100 || high < 0) {
                                high = 0;
                            }
                            
                            if (ph > 14 || ph < 0) {
                                ph = 0.0;
                            }
                            
                            if (highTemperature > 100 || highTemperature < 0) {
                                highTemperature = 0;
                            }
                            
                            if (temperature > 100 || temperature < 0) {
                                temperature = 0;
                            }
                            
                            device.temperature = temperature;
                            device.lock = lock;
                            device.low = low;
                            device.high = high;
                            device.failureState = failureState;
                            device.waterTemperature = waterTemperature;
                            device.lamp = lamp;
                            device.waterPump = waterPump;
                            device.floodlight = floodlight;
                            device.standbyPower = standbyPower;
                            device.waterLevel = waterLevel;
                            device.pH = pH;
                            device.password = password;
                            device.highTemperature = highTemperature;
                                   
                            NSString * status = [NSString stringWithFormat:@"%d", lock];
                            NSString * lockString;
                            NSString * waterTemperatureString;
                            NSString * lampString;
                            NSString * waterPumpString;
                            NSString * floodlightString;
                            NSString * standbyPowerString;
                            NSString * waterLevelString;
                            NSString * phString;
                            if (lock > 0) {
                                lockString = @"设备已锁定";
                            }else{
                                lockString = @"设备未锁定";
                            }
                                   
                                   
                            if (waterTemperature == 0) {
                                waterTemperatureString = @"水温正常";
                            }else if (waterTemperature == 1){
                                waterTemperatureString = @"水温过低";
                            }else if (waterTemperature == 2){
                                waterTemperatureString = @"水温过高";
                            }
                                   
                            
                            if (lamp > 0) {
                                lampString = @"杀菌灯故障";
                            }else{
                                lampString = @"杀菌灯正常";
                            }
                                   
                            if (waterPump > 0){
                                waterPumpString = @"冲浪水泵故障";
                            }else{
                                waterPumpString = @"冲浪水泵正常";
                            }
                                   
                                   
                            if (floodlight > 0) {
                                floodlightString = @"灯光故障";
                            }else{
                                floodlightString = @"灯光正常";
                            }
                                   
                            if (standbyPower > 0) {
                                standbyPowerString = @"备用电源故障";
                            }else{
                                standbyPowerString = @"备用电源正常";
                            }
                                   
                            if (waterLevel > 0) {
                                waterLevelString = @"水位过低";
                            }else{
                                waterLevelString = @"水位正常";
                            }
                                   
                            if (pH == 0) {
                                phString = @"PH正常";
                            }else if (pH == 1){
                                phString = @"PH过低";
                            }else if (pH == 2){
                                phString = @"PH过高";
                            }
                                   
                                   
                            NSString * stateString = [NSString stringWithFormat:@"设备时间=%@\n锁定状态lock ＝ %@\n温度temperature = %f\nph = %f\n水温waterTemperature = %@\n杀菌灯lamp = %@\n冲浪水泵waterPump = %@\n照明灯floodlight = %@\n备用电源standbyPower = %@\n水位waterLevel = %@\nPH状态 = %@\n高温阙值 ＝ %d\n低温阙值 ＝ %d\n高温设置 ＝ %d",[self getDateFromGlobalState:bodyBuf :bodySize],lockString, temperature, ph,waterTemperatureString, lampString, waterPumpString, floodlightString, standbyPowerString, waterLevelString, phString, high, low, highTemperature];
                            
                            device.state = stateString;
                            self.errorOfSensorCnt = 0;
                            dispatch_async(dispatch_get_main_queue(), ^{
                                updated(temperature, ph, bodyBuf[5], status);
                            });
                          }
                        
                    }else{
                        
                        NSLog(@"PPPP_Read ret1 = %d , msg= %@", ret,[DeviceCtrl getPPPPReadMsg:ret]);
                               
                        dispatch_async(dispatch_get_main_queue(), ^{
                            self.errorOfSensorCnt++;
                            interupted(ret);
                        });
                               
                    }//end else
                    
                    if(self.errorOfSensorCnt > 0){
                        NSLog(@"错误errorOfSensorCnt= %d",self.errorOfSensorCnt);
                    }
                    
                    [NSThread sleepForTimeInterval:1];
                }// end while
        
    });//END dispatch
    
}

- (void) listenOnVideoWithTimeout: (NSUInteger)timeout
                         password: (NSString *)password
                          updated:(void (^)(NSData *data))updated
                       interupted:(void (^)(NSInteger errorCode))interupted
{
    _isListenOnVideo = YES;
    dispatch_async(self.videoQueue, ^
   {
       [self sendStartVideoRequest:password];
       
       NSLog(@"开始监听摄像头.......");
       
       while (_isListenOnVideo)
       {
           if(self.errorOfVideoCnt > MAX_VIDEO_ERROR_CNT){
               
               dispatch_async(dispatch_get_main_queue(), ^{
                   self.errorOfVideoCnt = 0;
                   interupted(ERROR_NEED_RECONNECT);
               });
               
               break;
           }
           
           int ret = -99;
           ClientPackHead headBuf;
           int headSize = sizeof(headBuf);
           ret = PPPP_Read(self.currentSession, (UCHAR)0, (CHAR *)&headBuf, &headSize, (UINT32)timeout);
           
           if (ERROR_PPPP_SUCCESSFUL == ret)
//               && 0xaa == headBuf.flag && CPT_MJPEG_FRAME == headBuf.type)
           {
               int bodySize = headBuf.length;
               if(bodySize <= 0){
                   dispatch_async(dispatch_get_main_queue(), ^{
                       self.errorOfVideoCnt++;
                       interupted(ret);
                   });
                   NSLog(@"PPPP读取listenOnVideoWithTimeout 2 %@",[DeviceCtrl getPPPPReadMsg:ret]);
                   continue;
               }
               char *bodyBuf = (char *)malloc(sizeof(char) * bodySize);
               NSInteger bodyRet = PPPP_Read(self.currentSession, (UCHAR)0, bodyBuf, &bodySize, (UINT32)timeout);
               if (bodyRet >= 0)
               {
                   NSData *bodyBackData = [NSData dataWithBytes:bodyBuf length:bodySize];
                   
                   dispatch_async(dispatch_get_main_queue(), ^{
                       NSLog(@"updated image");
                       updated(bodyBackData);
                       self.errorOfVideoCnt=0;
                   });
               }else{
                   
                   dispatch_async(dispatch_get_main_queue(), ^{
                       self.errorOfVideoCnt++;
                       interupted(ret);
                   });
                   
                   NSLog(@"PPPP读取listenOnVideoWithTimeout 2 %@",[DeviceCtrl getPPPPReadMsg:ret]);
               }
           }else{
               
               dispatch_async(dispatch_get_main_queue(), ^{
                   self.errorOfVideoCnt++;
                   interupted(ret);
               });
               NSLog(@"PPPP读取listenOnVideoWithTimeout  1%@",[DeviceCtrl getPPPPReadMsg:ret]);
           }
           //
           if(self.errorOfVideoCnt > 0){
               NSLog(@"errorOfVideoCnt= %d",self.errorOfVideoCnt);
           }
           NSLog(@"listenning");
           [NSThread sleepForTimeInterval:0.1];
           
       }//end while
   
   });
}

- (void) controlPeriodWith:(ControlType)controlType
                  password:(NSString *)password
                   success:(void (^)(ControlPeriods *controlPeriods))success
                   failure:(void (^)(NSInteger errorCode))failure
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSInteger ret = -99;
        
        [self sendSensorReadingRequest:password];
        [NSThread sleepForTimeInterval:1];
        
        ClientPackHead headBuf;
        int headSize = sizeof(headBuf);
        ret = PPPP_Read(self.currentSession, (UCHAR)1, (CHAR *)&headBuf, &headSize, 0xffffffff);
        if (ERROR_PPPP_SUCCESSFUL <= ret && 0xaa == headBuf.flag && CPT_MCU_COMM_FB == headBuf.type)
        {
            int bodySize = headBuf.length;
            char *bodyBuf = (char *)malloc(sizeof(char) * bodySize);
            NSInteger bodyRet = PPPP_Read(self.currentSession, (UCHAR)1, bodyBuf, &bodySize, 0xffffffff);
            if (bodyRet >= 0)
            {
                NSData *bodyBackData = [NSData dataWithBytes:bodyBuf length:bodySize];
                NSLog(@"bodyBuf read = %@", bodyBackData);
                
                int startIndex = 13 + 6 * controlType;
                char periodsData[6];
                memcpy(periodsData, &bodyBuf[startIndex], sizeof(periodsData));
                ControlPeriods *controlPeriods = [[ControlPeriods alloc] initWithPeriodData:periodsData];
                [controlPeriods setType:controlType];
                
                dispatch_async(dispatch_get_main_queue(), ^{
                    success(controlPeriods);
                });
            }
            else
            {
                failure(bodyRet);
            }
        }
        else
        {
            failure(ret);
        }
    });
}


//水温异常上下限温度设置
- (void)setHighOrLowTemperatureWithHigh:(NSInteger)high
                                    low:(NSInteger)low
                               password:(NSString *)password
                                success:(void (^)())success
                                failure:(void (^)(NSInteger errorCode))failure{
    UInt8 data[6];
    data[0] = 0x16;
    data[1] = 0x00;
                               
    NSInteger highT = high * 10;
    NSInteger lowT = low * 10;
    data[2] = lowT >> 8  ;
    data[3] = lowT &0x00ff;
    data[4] = highT >> 8;
    data[5] = highT &0x00ff;
                               
                               
    SetPeriodsRequest request;
    request.head.flag = 0xaa;
    request.head.type = CPT_MCU_COMM;
    request.head.length = (int)(sizeof(data) / sizeof(data[0])) + 18;//18 == sizeof(pwd)+sizeof(mode) + sizeof(length)
                               
    memcpy(request.body.devPwd, [password UTF8String], sizeof(request.body.devPwd));
    request.body.mode = SET;
    request.body.length = (int)(sizeof(data) / sizeof(data[0]));
    memcpy(request.body.content, data, sizeof(data));
    
    NSData *requestBodyInByte = [NSData dataWithBytes:&request length:sizeof(request)];
    
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        int ret =PPPP_Write(self.currentSession, (UCHAR)1, (CHAR *)[requestBodyInByte bytes], sizeof(request));
        if(ret >= 0){
            dispatch_async(dispatch_get_main_queue(), ^{
                success();
            });
            
        }else{
            
            dispatch_async(dispatch_get_main_queue(), ^{
                failure(ret);
            });

        }
        NSLog(@"水温异常上下限温度设置 PPPP_Write ret = %d, msg= %@", ret,[DeviceCtrl getPPPPWriteMsg:ret]);
        
    });
    
    
}



- (void) setControlPeriod:(ControlPeriods *)controlPeriods
                 password:(NSString *)password
                  success:(void (^)())success
                  failure:(void (^)(NSInteger errorCode))failure
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
    {
        NSInteger ret = -99;
        [self sendSensorReadingRequest:password];
        [NSThread sleepForTimeInterval:1];
        
        ClientPackHead headBuf;
        int headSize = sizeof(headBuf);
        ret = PPPP_Read(self.currentSession, (UCHAR)1, (CHAR *)&headBuf, &headSize, 0xffffffff);
        if (ERROR_PPPP_SUCCESSFUL <= ret && 0xaa == headBuf.flag && CPT_MCU_COMM_FB == headBuf.type)
        {
            int bodySize = headBuf.length;
            char *bodyBuf = (char *)malloc(sizeof(char) * bodySize);
            NSInteger bodyRet = PPPP_Read(self.currentSession, (UCHAR)1, bodyBuf, &bodySize, 0xffffffff);
            
            NSData *bodyBackData = [NSData dataWithBytes:bodyBuf length:bodySize];
            NSLog(@"bodyBuf read = %@", bodyBackData);
            if (bodyRet >= 0)
            {
                /** Get original periods data*/
                char periodsData[18];
                memcpy(periodsData, &bodyBuf[13], sizeof(periodsData));
                
                NSData *bodyBackperiodsData = [NSData dataWithBytes:periodsData length:18];
                NSLog(@"bodyBuf periods data read = %@", bodyBackperiodsData);
                
                /** Modify the period data*/
                char dataNeedToBeSet[6];
                [controlPeriods data:dataNeedToBeSet];
                int startIndex = 6 * controlPeriods.type;
                memcpy(&periodsData[startIndex], dataNeedToBeSet, sizeof(dataNeedToBeSet));
                
                /** Write it back*/
                UInt8 data[19];
                data[0] = 0x09;
                memcpy(&data[1], periodsData, sizeof(periodsData));
                
                SetPeriodsRequest request;
                request.head.flag = 0xaa;
                request.head.type = CPT_MCU_COMM;
                request.head.length = (int)(sizeof(data) / sizeof(data[0])) + 18;//18 == sizeof(pwd)+sizeof(mode) + sizeof(length)
                
                memcpy(request.body.devPwd, [password UTF8String], sizeof(request.body.devPwd));
                request.body.mode = SET;
                request.body.length = (int)(sizeof(data) / sizeof(data[0]));
                memcpy(request.body.content, data, sizeof(data));
                
                NSData *requestBodyInByte = [NSData dataWithBytes:&request length:sizeof(request) - 1];
                NSLog(@"requestBodyInByte send = %@", requestBodyInByte);
                PPPP_Write(self.currentSession, (UCHAR)1, (CHAR *)[requestBodyInByte bytes], sizeof(request));
                
                dispatch_async(dispatch_get_main_queue(), ^{
                    success();
                });
            }
            else
            {
                failure(bodyRet);
            }
        }
        else
        {
            failure(ret);
        }
    });
}

/**
 *  读取全局状态 请求发送
 */
- (int)sendSensorReadingRequest:(NSString *)password
{
    /** Build the request data block*/
    UInt8 data[2];
    data[0] = 0x03;
    data[1] = 0x03;
    
    ControlRequest request;
    request.head.flag = 0xaa;
    request.head.type = CPT_MCU_COMM;
    request.head.length = 2 + 18;//18 == sizeof(pwd)+sizeof(mode) + sizeof(length)
    memcpy(request.body.devPwd, [password UTF8String], sizeof(request.body.devPwd));
    request.body.mode = READ;
    request.body.length = 2;
    memcpy(request.body.content, data, sizeof(data));

    NSData *requestBodyInByte = [NSData dataWithBytes:&request length:sizeof(request)];
    
    return PPPP_Write(self.currentSession, (UCHAR)1, (CHAR *)[requestBodyInByte bytes], sizeof(request));
}

- (NSInteger) setLightStatus:(BOOL)lightStatus
                 waterStatus:(BOOL)waterStatus
             disinfectStatus:(BOOL)disinfectStatus
           autoControlStatus:(BOOL)autoControlStatus
                withPassword:(NSString *)password;
{
    UInt8 data[2];
    data[0] = 0x02;
    
    data[1] = 0x00;
    data[1] = lightStatus? (data[1]|0x01):(data[1]&0xfe);
    data[1] = waterStatus? (data[1]|0x02):(data[1]&0xfd);
    data[1] = disinfectStatus? (data[1]|0x10):(data[1]&0xef);//0x10 == 0001 0000 ; 0xef == 1110 1111
    data[1] = autoControlStatus? (data[1]|0x80):(data[1]&0x7f);//0x80 == 1000 0000; 0x7f == 01111 1111
    
    ControlRequest request;
    request.head.flag = 0xaa;
    request.head.type = CPT_MCU_COMM;
    request.head.length = (int)(sizeof(data) / sizeof(data[0])) + 18;//18 == sizeof(pwd)+sizeof(mode) + sizeof(length)
    
    memcpy(request.body.devPwd, [password UTF8String], sizeof(request.body.devPwd));
    request.body.mode = SET;
    request.body.length = (int)(sizeof(data) / sizeof(data[0]));
    memcpy(request.body.content, data, sizeof(data));
    
    NSData *requestBodyInByte = [NSData dataWithBytes:&request length:sizeof(request)];
    return PPPP_Write(self.currentSession, (UCHAR)1, (CHAR *)[requestBodyInByte bytes], sizeof(request));
}

- (NSInteger) sendStartVideoRequest:(NSString *)password
{
    /** Build the request data block*/    
    VideoStartRequest request;
    request.head.flag = 0xaa;
    request.head.type = CPT_MJPEG_START;
    request.head.length = sizeof(VideoStartData);//16 + 8
    
    memcpy(request.body.devPwd, [password UTF8String], sizeof(request.body.devPwd));
    request.body.count = 1000;
    request.body.frameCycle = 120;
    request.body.height = 240;
    request.body.width = 320;
    
    NSData *requestBodyInByte = [NSData dataWithBytes:&request length:sizeof(request)];
    return PPPP_Write(self.currentSession, (UCHAR)1, (CHAR *)[requestBodyInByte bytes], sizeof(request));
}

- (NSInteger) sendStopVideoRequest:(NSString *)password
{
    /** Build the request data block*/
    VideoStopRequest request;
    request.head.flag = 0xaa;
    request.head.type = CPT_MJPEG_STOP;
    request.head.length = sizeof(VideoStopData);
    
    memcpy(request.body.devPwd, [password UTF8String], sizeof(request.body.devPwd));
    
    NSData *requestBodyInByte = [NSData dataWithBytes:&request length:sizeof(request)];
    return PPPP_Write(self.currentSession, (UCHAR)1, (CHAR *)[requestBodyInByte bytes], sizeof(request));
}


-(void)close{
    NSLog(@"关闭Apis");
    __block int sessionID = self.currentSession;
    dispatch_async(self.closeQueue, ^{
        
        int ret = PPPP_Connect_Break();
        NSLog(@"%d,%@",ret, [DeviceCtrl getPPPPConnectErrMsg:ret]);
        NSLog(@"设备关闭指令");
        [[APIs sharedInstance] setIsListenOnSensors:NO];
        [[APIs sharedInstance] setIsListenOnVideo:NO];
        
        if(sessionID > -1){
            int ret = PPPP_Close(sessionID);
            NSLog(@"%@", [DeviceCtrl getPPPPCloseMsg:ret]);
        }
    });
    
}



-(void)close:(INT32 ) sessionID{
    NSLog(@"关闭Apis");
    
    dispatch_async(self.closeQueue, ^{
        
        int ret = PPPP_Connect_Break();
        NSLog(@"%d,%@",ret, [DeviceCtrl getPPPPConnectErrMsg:ret]);
        NSLog(@"设备关闭指令");
        [[APIs sharedInstance] setIsListenOnSensors:NO];
        [[APIs sharedInstance] setIsListenOnVideo:NO];
        
        if(sessionID > -1){
            int ret = PPPP_Close(sessionID);
            NSLog(@"%@", [DeviceCtrl getPPPPCloseMsg:ret]);
        }
    });
    
}


//同步时间
- (void) syncTimeToDevice: (NSString *)password
                  success:(void (^)())success
                interupted:(void (^)(NSInteger errorCode))interupted
{
    
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
    /** Build the request data block*/
    SyncTimeRequest  request;
    request.head.flag = 0xaa;
    request.head.type = CPT_MCU_COMM;
    request.head.length = sizeof(SyncTimeData);//16 + 8
    
    memcpy(request.body.devPwd, [password UTF8String], sizeof(request.body.devPwd));
    request.body.mode = SET;
    request.body.length = 8;
    
    NSDate *date = [NSDate defaultCurrentDate] ;
    
    NSCalendar * calendar = [NSCalendar currentCalendar];
    NSInteger hour =0 ;
    NSInteger minute = 0;
    NSInteger second = 0;
    NSInteger nanosecond = 0;
    NSInteger year = 0;
    NSInteger month = 0;
    NSInteger day = 0;
    NSInteger era = 0;
        
//    if(SYSTEM_VERSION_GREATER_THAN(@"8.0")){
//        [calendar getHour:&hour minute:&minute second:&second nanosecond:&nanosecond fromDate:date];
//        [calendar getEra:&era year:&year month:&month day:&day fromDate:date];
//    }else{
        NSUInteger unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSCalendarUnitNanosecond | NSEraCalendarUnit;
        
        NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:date];
        hour = dateComponent.hour;
        minute = dateComponent.minute;
        second = dateComponent.second;
        nanosecond = dateComponent.nanosecond;
        year = dateComponent.year;
        month = dateComponent.month;
        day = dateComponent.day;
        era = dateComponent.era;
//    }
        
    NSLog(@"era=%ld year = %ld month= %ld day = %ld",era,year,month,day);
    
    NSLog(@"hour=%ld minute = %ld second = %ld nanosecond = %ld",hour, minute , second,nanosecond);
    year = year - 2000;
    if(year < 0  && year > 100){
        year  = 0;
    }
//        minute = 10;
    Byte timeContent[8];
    timeContent[0] = 0x07;
    timeContent[1] = 0xFF & year;
    timeContent[2] = 0xFF &  month;
    timeContent[3] = 0xFF &  day;
//        timeContent[1] = 0x15;
//        timeContent[2] = 0x01;
//        timeContent[3] = 0x01;
    timeContent[4] = 0x00;
    timeContent[5] = 0xFF & hour;
//        [[NSNumber numberWithInteger:minute] integerValue];
    timeContent[6] = 0xFF & minute;
    timeContent[7] = 0xFF & second;
        
    memcpy(request.body.content, timeContent, 8);
    NSLog(@"timeContent = %s",timeContent);
    
    NSData *requestBodyInByte = [NSData dataWithBytes:&request length:sizeof(request)];
    int ret = PPPP_Write(self.currentSession, (UCHAR)1, (CHAR *)[requestBodyInByte bytes], sizeof(request));
        
        if (ret >= 0){
            
            dispatch_async(dispatch_get_main_queue(), ^{
                success();
            });
            
        }else{
            
            dispatch_async(dispatch_get_main_queue(), ^{
                interupted(ret);
            });
        }
    
    
    });
    
}


- (void) querySubscribeToken: (UINT32)timeout
                     password: (NSString *)password
                      success:(void (^)(NSString * temperature , NSString * level, NSString * load))success
                  interupted:(void (^)(NSInteger errorCode))interupted
{
    
    dispatch_async(self.controlQueue, ^{
        NSLog(@"开始异步查询订阅令牌.......");
        
        INT32 ret = -99;
        /** Build the request data block*/
        UInt8 data[3];
        data[0] = 0x15;
        data[1] = 0x00;
        data[2] = 0x00;
        data[2] = data[2] | 0x04; //请求负载设备订阅信息
        data[2] = data[2] | 0x02; //请求负载设备订阅信息
        data[2] = data[2] | 0x01; //请求水温报警订阅信息
        
        SubsribeTokenRequest request;
        request.head.flag = 0xaa;
        request.head.type = CPT_MCU_COMM;
        request.head.length = 3 + 18;
        memcpy(request.body.devPwd, [password UTF8String], sizeof(request.body.devPwd));
        request.body.mode = READ;
        request.body.length = 3;
        memcpy(request.body.content, data, sizeof(data));
        
        NSData *requestBodyInByte = [NSData dataWithBytes:&request length:sizeof(request)];
        
        ret = PPPP_Write(self.currentSession, (UCHAR)1, (CHAR *)[requestBodyInByte bytes], sizeof(request));
        
        if(ret < 0){
            NSLog(@"设备令牌获取请求= %@",[DeviceCtrl getPPPPWriteMsg:ret]);
            dispatch_async(dispatch_get_main_queue(), ^{
                interupted(0);
            });
            return ;
        }
        
        
        BOOL isSuccess = NO;
        ClientPackHead headBuf;
        int headSize = sizeof(headBuf);
        ret = PPPP_Read(self.currentSession, (UCHAR)1, (CHAR *)&headBuf, &headSize, timeout);
        
        NSLog(@"令牌订阅信息获取 PPPP_Read ＝ %d desc= %@", ret,[DeviceCtrl getPPPPReadMsg:ret]);
        
        if (ERROR_PPPP_SUCCESSFUL == ret && 0xaa == headBuf.flag && CPT_MCU_COMM_FB == headBuf.type)
        {
            int bodySize = headBuf.length;
            char *bodyBuf = (char *)malloc(sizeof(char) * bodySize);
            INT32 bodyRet = PPPP_Read(self.currentSession, (UCHAR)1, bodyBuf, &bodySize, timeout);
            
            NSLog(@"bodyRet ＝ %d desc= %@", bodyRet,[DeviceCtrl getPPPPReadMsg:bodyRet]);
            
            if (bodyRet == ERROR_PPPP_SUCCESSFUL && bodyBuf[0] == 0x15)
            {
                int size = (int)bodyBuf[1];
                if(size == 3){
                    
                    int indexOfZeroFlag[3];
                    int j = 0;
                    NSMutableString * str1 = [[NSMutableString alloc] init];
                    NSMutableString * str2 = [[NSMutableString alloc] init];
                    NSMutableString * str3 = [[NSMutableString alloc] init];
                    for (int i = 2; i < bodySize; i++) {
                        if (bodyBuf[i] == 0x00) {
                            indexOfZeroFlag[j] = i;
                            j++;
                        }
                        if(j == 0){
                            [str1 appendFormat:@"%c",bodyBuf[i]];
                        }
                        if(j == 1){
                            [str2 appendFormat:@"%c",bodyBuf[i]];
                        }
                        if(j == 2){
                            [str3 appendFormat:@"%c",bodyBuf[i]];
                        }
                    }
                    
                    
                    
                    NSLog(@"订阅信息组的项数量%d,0=%d 1=%d 2=%d",size,indexOfZeroFlag[0],indexOfZeroFlag[1],indexOfZeroFlag[2]);
                    
                    
                    NSLog(@"str1= %@,str2= %@,str3= %@",str1,str2,str3);
                    
                    isSuccess = YES;
                    
                    dispatch_async(dispatch_get_main_queue(), ^{
                        success(str1, str2,str3);
                    });
                    
                }
                
                
            }
        }
        
        if(!isSuccess){
            dispatch_async(dispatch_get_main_queue(), ^{
                interupted(0);
            });
        }
        
        
        
    });
}


-(NSString *) getDateFromGlobalState:(char *) bodyBuf :(int) bodySize{
    
    if(bodySize > 12){
        //6-12
        int year = (int) bodyBuf[6];
        int month = (int) bodyBuf[7];
        int day = (int) bodyBuf[8];
        
        
//        int week = (int) bodyBuf[9];
        int hour = (int) bodyBuf[10];
        int min = (int) bodyBuf[11];
        int second = (int) bodyBuf[12];
        
        
        NSString * strDate = [NSString stringWithFormat:@"%d-%d-%d %d:%d:%d",(year+2000),month,day,hour,min,second];
        
        DeviceSun * device = [DeviceSun defaultDevice];
        device.datetime = strDate;
//        NSLog(@"获取到的设备时间= %@",strDate);
        return strDate;
    }
    
    return @"-";
}


-(void) setTemperature:(UINT16 ) temp
              password: (NSString *)password
               success:(void (^)())success
            interupted:(void (^)(NSInteger errorCode))interupted{
    
    NSLog(@"开始异步设置加热上限温度1.......");
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"开始异步设置加热上限温度2.......");
        
        INT32 ret = -99;
        
        UInt8 data[3];
        data[0] = 0x0d;
        data[1] = (UInt8) (temp >> 8) ;
        data[2] = (UInt8) (temp & 0x00ff) ;
        
        SetTemperatureRequest request;
        request.head.flag = 0xaa;
        request.head.type = CPT_MCU_COMM;
        request.head.length = 3 + 18;
        memcpy(request.body.devPwd, [password UTF8String], sizeof(request.body.devPwd));
        request.body.mode = SET;
        
        request.body.length = 3;
        memcpy(request.body.content, data, sizeof(data));
        
        NSData *requestBodyInByte = [NSData dataWithBytes:&request length:sizeof(request)];
        
        ret = PPPP_Write(self.currentSession, (UCHAR)1, (CHAR *)[requestBodyInByte bytes], sizeof(request));
        
        NSLog(@"温度设置请求= %@",[DeviceCtrl getPPPPWriteMsg:ret]);
        
        if(ret < 0){
            dispatch_async(dispatch_get_main_queue(), ^{
                interupted(ret);
            });
            
        }else{
            
            dispatch_async(dispatch_get_main_queue(), ^{
                    success();
            });
        }
        
        
    });

    
}


#pragma -mark- Setter and Getter
- (dispatch_queue_t)controlQueue
{
    if (!_controlQueue)
    {
        _controlQueue = dispatch_queue_create(CONTROL_QUEUE, DISPATCH_QUEUE_SERIAL);
    }
    return _controlQueue;
}

- (dispatch_queue_t)videoQueue
{
    if (!_videoQueue)
    {
        _videoQueue = dispatch_queue_create(VIDEO_QUEUE, DISPATCH_QUEUE_SERIAL);
    }
    return _videoQueue;
}

- (dispatch_queue_t)closeQueue
{
    if (!_closeQueue)
    {
        _closeQueue = dispatch_queue_create("CLOSE_QUEUE", DISPATCH_QUEUE_SERIAL);
    }
    return _closeQueue;
}


@end
